/*
 * FreeRTOS Kernel V10.5.1
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * SPDX-License-Identifier: MIT
 *
 */

#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#ifndef INC_FREERTOS_H
    #error "include FreeRTOS.h" must appear in source files before "include semphr.h"
#endif

#include "queue.h"

typedef QueueHandle_t SemaphoreHandle_t;

#define semBINARY_SEMAPHORE_QUEUE_LENGTH    ( ( uint8_t ) 1U )
#define semSEMAPHORE_QUEUE_ITEM_LENGTH      ( ( uint8_t ) 0U )
#define semGIVE_BLOCK_TIME                  ( ( TickType_t ) 0U )


/**
 * 创建二值信号量
 */
#define vSemaphoreCreateBinary(xSemaphore)                                                                                   \
{                                                                                                                            \
    (xSemaphore) = xQueueGenericCreate((UBaseType_t)1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );   \
    if ((xSemaphore) != NULL)                                                                                                 \
    {                                                                                                                        \
        (void) xSemaphoreGive((xSemaphore));                                                                                 \
    }                                                                                                                        \
}

/*
 * 创建二值信号量
 */
#define xSemaphoreCreateBinary()  \
    xQueueGenericCreate((UBaseType_t)1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE)

/**
 * 获取信号量
 */
#define xSemaphoreTake(xSemaphore, xBlockTime)    xQueueSemaphoreTake((xSemaphore), (xBlockTime))

/**
 */
#if ( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreTakeRecursive(xMutex, xBlockTime)    \
    xQueueTakeMutexRecursive((xMutex), (xBlockTime))
#endif

/**
 * 释放信号量
 */
#define xSemaphoreGive(xSemaphore)    \
    xQueueGenericSend((QueueHandle_t) (xSemaphore), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK)

/**
 */
#if (configUSE_RECURSIVE_MUTEXES == 1)
#define xSemaphoreGiveRecursive(xMutex)    xQueueGiveMutexRecursive((xMutex))
#endif

/**
 * 释放信号量
 */
#define xSemaphoreGiveFromISR(xSemaphore, pxHigherPriorityTaskWoken)    \
    xQueueGiveFromISR((QueueHandle_t) (xSemaphore), (pxHigherPriorityTaskWoken))

/**
 * 获取信号量
 */
#define xSemaphoreTakeFromISR(xSemaphore, pxHigherPriorityTaskWoken)    \
    xQueueReceiveFromISR((QueueHandle_t) (xSemaphore), NULL, (pxHigherPriorityTaskWoken))

/**
 * 创建互斥量
 */
#if (configUSE_MUTEXES == 1)
    #define xSemaphoreCreateMutex()    xQueueCreateMutex(queueQUEUE_TYPE_MUTEX)
#endif

/**
 */
#if (configUSE_RECURSIVE_MUTEXES == 1)
#define xSemaphoreCreateRecursiveMutex()  xQueueCreateMutex(queueQUEUE_TYPE_RECURSIVE_MUTEX)
#endif

/**
 * 创建计数型信号量
 */
 #define xSemaphoreCreateCounting(uxMaxCount, uxInitialCount)    \
        xQueueCreateCountingSemaphore((uxMaxCount), (uxInitialCount))

/**
 * 删除信号量
 */
#define vSemaphoreDelete(xSemaphore)  vQueueDelete((QueueHandle_t) (xSemaphore))

/**
 */
#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
    #define xSemaphoreGetMutexHolder( xSemaphore )    xQueueGetMutexHolder( ( xSemaphore ) )
#endif

/**
 */
#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
    #define xSemaphoreGetMutexHolderFromISR(xSemaphore)    xQueueGetMutexHolderFromISR((xSemaphore))
#endif

/**
 * 获取信号量计数值
 */
#define uxSemaphoreGetCount(xSemaphore)   uxQueueMessagesWaiting((QueueHandle_t)(xSemaphore))

/**
 * 获取信号量计数值
 */
#define uxSemaphoreGetCountFromISR(xSemaphore)  uxQueueMessagesWaitingFromISR((QueueHandle_t) (xSemaphore))

#endif /* SEMAPHORE_H */
